//
//  ChatMessagesDataBase.m
//  AAIM
//
//  Created by awh on 2019/12/23.
//  Copyright © 2019年 AAIM. All rights reserved.
//

#import "ChatMessagesDataBase.h"
#import "BTMessageModel.h"
#import "TextMessageModel.h"
#import "ImageMessageModel.h"
#import "VoiceMessageModel.h"



@interface ChatMessagesDataBase ()

//@property(nonatomic, strong) FMDatabase *db;   // 数据数据库
@property(nonatomic, strong) FMDatabaseQueue *dbqueue;
@property(nonatomic, copy) NSString *tableName; // 表名，每个表为当前登录用户与所有好友的聊天记录


@end
@implementation ChatMessagesDataBase
//SingleM(ChatMessagesDataBase);

static ChatMessagesDataBase *single = nil;
+ (instancetype)shareChatMessagesDataBase {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        single = [[self alloc] init];
    });
    return single;
}

- (instancetype)init {
    if (self = [super init]) {
        [self initDataBase];
    }
    return self;
}

- (void)initDataBase {
    NSString *dbPath  =[CacheTool readUserDefaults:@"APPDATABASE_KEY"];
    self.dbqueue = [[FMDatabaseQueue alloc] initWithPath:dbPath];
}

- (void)creatChatTable {
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        NSString *createTableSql = [NSString stringWithFormat:@"create table if not exists %@ ('ID' INTEGER PRIMARY KEY AUTOINCREMENT, 'messageDirection' INTEGER, 'messageType' INTEGER,'uid' INTEGER, 'username' TEXT, 'avatar' TEXT, 'type' TEXT, 'src' TEXT, 'content' TEXT, 'time' TEXT, 'specialType' INTEGER, 'groupId' INTEGER, 'authority' INTEGER, 'mine' INTEGER, 'timestamp' INTEGER, 'cid' INTEGER, 'receiveUid' INTEGER, 'unreadCount' INTEGER, 'path' TEXT, 'image' BLOB, 'duration' INTEGER, 'messageStatus' INTEGER, 'updateTimestamp' INTEGER, 'messageId' INTEGER , 'msgtype' INTEGER, 'msg_id' TEXT, 'clientuuid' TEXT, 'createtime' TEXT, 'msg' TEXT, 'gId' TEXT, 'head' TEXT, 'f_uuid' TEXT, 'nickname' TEXT, 'token' TEXT, 'udid' TEXT, 'rfuuid' TEXT, 'chatType' INTEGER)", self.tableName];
        [db executeUpdate:createTableSql];
    }];
}

- (void)insertMessage:(BTMessageModel *)msg{
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        NSString *tableNameHead = [NSString stringWithFormat:@"insert into '%@' ", self.tableName];
        long long insertTime = [ChatTool shareChatTool].currentTimestamp;
        long long messageId = msg.messageDirection == MessageDirectionSend ? 0 : [msg.msg_id integerValue];
        BOOL result = NO;
        
        if (msg.msgtype == MessageTypeText || msg.msgtype == MessageTypeRecall || msg.msgtype == MessageTypeTime || msg.msgtype == MessageTypeInviteAddGroup ||msg.msgtype == MessageTypeMangerDeleteMember ||msg.msgtype == MessageTypeGroupDissolution ||msg.msgtype == MessageTypeStartGroupChatting ||msg.msgtype == MessageTypeAddedBlacklist ||msg.msgtype == MessageTypeNotInGroup ||msg.msgtype == MessageTypeNotFriend ||msg.msgtype == MessageTypeSendFailure||msg.msgtype == MessageTypeSendBanned ) {
            NSString *content = [NSString stringWithFormat:@"(messageDirection, messageType, uid, username, avatar, type, src, content, time, specialType, groupId, authority, mine, timestamp, updateTimestamp, cid, receiveUid, unreadCount, messageStatus, messageId, msgtype, msg , msg_id ,clientuuid , createtime, gId , head ,f_uuid ,nickname,token,udid,rfuuid,chatType) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)"];
            NSString *sql = [NSString stringWithFormat:@"%@%@", tableNameHead, content];
            result = [db executeUpdate:sql, @(msg.messageDirection), @(msg.messageType), @(msg.uid), msg.username, msg.avatar, msg.type, msg.src, msg.content, msg.time, @(msg.specialType), @(msg.groupId), @(msg.authority), @(msg.mine), @(msg.timestamp), @(insertTime), @(msg.cid), @(msg.receiveUid), @(msg.unreadCount), @(msg.messageStatus), @(messageId),@(msg.msgtype),msg.msg,msg.msg_id,msg.clientuuid,msg.createtime,msg.gId,msg.head,msg.fuuid,msg.nickname,msg.token,msg.udid,msg.rfuuid,@(msg.chatType)];
        } else if (msg.msgtype == MessageTypeImage) {
            ImageMessageModel *imageMsg = (ImageMessageModel *)msg;
            NSData *imageData = UIImagePNGRepresentation(imageMsg.image);
            NSString *content = [NSString stringWithFormat:@"(messageDirection, messageType, uid, username, avatar, type, src, content, time, specialType, groupId, authority, mine, timestamp, updateTimestamp, cid, receiveUid, unreadCount, path, image, messageStatus, messageId,msgtype, msg , msg_id ,clientuuid , createtime, gId , head ,f_uuid ,nickname,token,udid,rfuuid,chatType) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"];
            NSString *sql = [NSString stringWithFormat:@"%@%@", tableNameHead, content];
            result = [db executeUpdate:sql, @(msg.messageDirection), @(msg.messageType), @(msg.uid), msg.username, msg.avatar, msg.type, msg.src, msg.content, msg.time, @(msg.specialType), @(msg.groupId), @(msg.authority), @(msg.mine), @(msg.timestamp), @(insertTime), @(msg.cid), @(msg.receiveUid), @(msg.unreadCount), imageMsg.path, imageData, @(imageMsg.messageStatus), @(messageId),@(msg.msgtype),msg.msg,msg.msg_id,msg.clientuuid,msg.createtime,msg.gId,msg.head,msg.fuuid,msg.nickname,msg.token,msg.udid,msg.rfuuid,@(msg.chatType)];
        } else if (msg.msgtype == MessageTypeVoice) {
            VoiceMessageModel *voiceMsg = (VoiceMessageModel *)msg;
            NSString *content = [NSString stringWithFormat:@"(messageDirection, messageType, uid, username, avatar, type, src, content, time, specialType, groupId, authority, mine, timestamp, updateTimestamp, cid, receiveUid, unreadCount, path, duration, messageStatus, messageId,msgtype, msg , msg_id ,clientuuid , createtime, gId , head ,f_uuid ,nickname,token,udid,rfuuid,chatType) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"];
            NSString *sql = [NSString stringWithFormat:@"%@%@", tableNameHead, content];
            result = [db executeUpdate:sql, @(msg.messageDirection), @(msg.messageType), @(msg.uid), msg.username, msg.avatar, msg.type, msg.src, msg.content, msg.time, @(msg.specialType), @(msg.groupId), @(msg.authority), @(msg.mine), @(msg.timestamp), @(insertTime), @(msg.cid), @(msg.receiveUid), @(msg.unreadCount), voiceMsg.path, @(voiceMsg.duration), @(voiceMsg.messageStatus), @(messageId),@(msg.msgtype),msg.msg,msg.msg_id,msg.clientuuid,msg.createtime,msg.gId,msg.head,msg.fuuid,msg.nickname,msg.token,msg.udid,msg.rfuuid,@(msg.chatType)];
        }
    }];
    
    // 更新最新头像
    [self updateAvatarWith:msg];
}

- (void)insertMessagArray:(NSArray<BTMessageModel *> *)messages {
    AAIMLog(@"开始批量插入单聊消息");
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        [db beginTransaction];
        BOOL isRollBack = NO;
        @try {
            NSString *tableNameHead = [NSString stringWithFormat:@"insert into '%@' ", self.tableName];
            long long insertTime = [ChatTool shareChatTool].currentTimestamp;
            __block BOOL result = NO;
            [messages enumerateObjectsUsingBlock:^(BTMessageModel * _Nonnull msg, NSUInteger idx, BOOL * _Nonnull stop) {
                long long messageId = msg.messageDirection == MessageDirectionSend ? 0 : [msg.msg_id integerValue];
                NSString *content = [NSString stringWithFormat:@"(messageDirection, messageType, uid, username, avatar, type, src, content, time, specialType, groupId, authority, mine, timestamp, updateTimestamp, cid, receiveUid, unreadCount, messageStatus, messageId , msg , msgtype ,msg_id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ,?)"];
                NSString *sql = [NSString stringWithFormat:@"%@%@", tableNameHead, content];
                result = [db executeUpdate:sql, @(msg.messageDirection), @(msg.messageType), @(msg.uid), msg.username, msg.avatar, msg.type, msg.src, msg.content, msg.time, @(msg.specialType), @(msg.groupId), @(msg.authority), @(msg.mine), @(msg.timestamp), @(insertTime), @(msg.cid), @(msg.receiveUid), @(msg.unreadCount), @(msg.messageStatus), @(messageId), msg.msg,msg.msgtype,msg.msg_id];
            }];
        } @catch (NSException *exception) {
            isRollBack = YES;
            [db rollback];
        } @finally {
            if (!isRollBack) {
                [db commit];
                AAIMLog(@"批量插入单聊消息完成");
            }
        }
    }];
}

// 更新最新头像
- (void)updateAvatarWith:(BTMessageModel *)msg {
    if (msg.messageType == MessageTypeText || msg.messageType == MessageTypeImage || msg.messageType == MessageTypeVoice) {
        [self.dbqueue inDatabase:^(FMDatabase *db) {
            NSString *sql = [NSString stringWithFormat:@"update %@ set avatar = '%@' where avatar != '%@' and uid = %ld", self.tableName, msg.avatar, msg.avatar, msg.rfuuid];
            [db executeUpdate:sql];
        }];
    }
}

- (BTMessageModel *)queryMessageWithTimestamp:(long long)timestamp {
    NSMutableArray *messages = [NSMutableArray new];
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"select * from %@ where (timestamp = %lld)", self.tableName, timestamp];
        FMResultSet *result = [db executeQuery:sql];
        while ([result next]) {
            [messages addObject:[self messageWith:result]];
        }
        
    }];
    if (messages.count) {
        return messages[0];
    } else {
        return nil;
    }
}

- (void)updateMessage:(BTMessageModel *)msg statusTo:(MessageStatus)status {
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"update %@ set messageStatus = %ld where timestamp = %lld;", self.tableName, status, msg.timestamp];
        [db executeUpdate:sql];
    }];
}

- (void)deleteMessage:(BTMessageModel *)msg {
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"delete from %@ where timestamp = %lld;", self.tableName, msg.timestamp];
        [db executeUpdate:sql];
    }];
}

// 清除时间戳之前的聊天记录
- (void)deleteMessageBeforeTimestamp:(long long)timestamp {
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"delete from %@ where updateTimestamp < %lld;", self.tableName, timestamp];
        [db executeUpdate:sql];
    }];
    
}

// 根据uid清空聊天记录
- (void)clearAllMessagesWithUid:(NSInteger)uid {
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"delete from %@ where (messageDirection = 0 and rfuuid = %ld) or (messageDirection = 1 and receiveUid = %ld)", self.tableName, uid, uid];
        [db executeUpdate:sql];
    }];
}

// 根据uid更新头像
- (void)updateAvatarWithUid:(NSInteger)uid avatar:(NSString *)avatar {
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"update %@ set head = '%@' where rfuuid = '%ld'", self.tableName, avatar, (long)uid];
        [db executeUpdate:sql];
    }];
}

// 根据uid更新昵称
- (void)updateUsernameWithUid:(NSInteger)uid username:(NSString *)username {
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"update %@ set username = '%@' where uid = '%ld'", self.tableName, username, (long)uid];
        [db executeUpdate:sql];
    }];
    
}

// 清空与所有好友的聊天记录
- (void)clearAllMessagesWithAllFriends {
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"delete from %@ ", self.tableName];
        [db executeUpdate:sql];
    }];
}

// 根据uid查询一条最新记录
- (BTMessageModel *)recentlyMessageWithUid:(NSInteger)uid {
    NSMutableArray *messages = [NSMutableArray new];
    // 发送给uid的消息  接收从uid发来的消息
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"select * from %@ where (messageDirection = 0 and rfuuid = %ld) or (messageDirection = 1 and receiveUid = %ld) order by timestamp desc limit 0,1", self.tableName, uid, uid];
        FMResultSet *result = [db executeQuery:sql];
        while ([result next]) {
            [messages addObject:[self messageWith:result]];
        }
    }];
    if (messages.count) {
        return messages[0];
    } else {
        return nil;
    }
}

// 根据uid查询所有聊天记录
- (NSArray<BTMessageModel *> *)queryAllMessagesWithUid:(NSInteger)uid {
    long long fromTime = [ChatTool shareChatTool].currentTimestamp - 3 * 60 * 60 * 1000;
    [self deleteMessageBeforeTimestamp:fromTime];
    NSMutableArray *messages = [NSMutableArray new];
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        // 发送给uid的消息  接收从uid发来的消息
        NSString *sql = [NSString stringWithFormat:@"select * from %@ where (messageDirection = 0 and rfuuid = %ld and updateTimestamp > %lld) or (messageDirection = 1 and rfuuid = %ld and updateTimestamp > %lld) order by timestamp asc", self.tableName, uid, fromTime, uid, fromTime];
        FMResultSet *result = [db executeQuery:sql];
        while ([result next]) {
            [messages addObject:[self messageWith:result]];
        }
    }];
    return messages;
}

//查询所有好友
- (NSArray<BTMessageModel *> *)queryFriendsMessagesWithKeyWord:(NSString *) keyWord {
    NSMutableArray *messages = [NSMutableArray new];
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"select * from %@ where  msg like '%%%@%%'", self.tableName,keyWord];
        FMResultSet *result = [db executeQuery:sql];
        while ([result next]) {
            [messages addObject:[self messageWith:result]];
        }
    }];
    return messages;
}

// 分页加载，每页20条
- (NSArray *)queryMessagesWithUid:(NSInteger)uid toTimestamp:(long long) toTimestamp {
//    long long fromTime = [ChatTool shareChatTool].currentTimestamp - 3 * 60 * 60 * 1000;
//    [self deleteMessageBeforeTimestamp:fromTime];
    NSMutableArray *messages = [NSMutableArray new];
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        
        if (toTimestamp == 0) { // 加载第一页
            NSString *sql = [NSString stringWithFormat:@"select * from %@ where (messageDirection = 0 and rfuuid = %ld) or (messageDirection = 1 and receiveUid = %ld) order by timestamp desc, msgType asc limit 0,20", self.tableName, uid, uid];
            FMResultSet *result = [db executeQuery:sql];
            while ([result next]) {
                [messages addObject:[self messageWith:result]];
            }
            
        } else {
            NSString *sql = [NSString stringWithFormat:@"select * from %@ where (messageDirection = 0 and rfuuid = %ld and timestamp < %lld) or (messageDirection = 1 and receiveUid = %ld and timestamp < %lld) order by timestamp desc, msgType asc limit 0,20", self.tableName, uid, toTimestamp, uid, toTimestamp];
            FMResultSet *result = [db executeQuery:sql];
            while ([result next]) {
                [messages addObject:[self messageWith:result]];
            }
        }
    }];
    return messages;
}

// 加载最新的count条数据
- (NSArray *)queryMessagesWithUid:(NSInteger)uid count:(NSInteger)count {
//    long long fromTime = [ChatTool shareChatTool].currentTimestamp - 3 * 60 * 60 * 1000;
//    [self deleteMessageBeforeTimestamp:fromTime];
    NSMutableArray *messages = [NSMutableArray new];
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"select * from %@ where (messageDirection = 0 and rfuuid = %ld) or (messageDirection = 1 and receiveUid = %ld) order by timestamp desc, msgtype asc limit 0,%ld", self.tableName, uid, uid, (long)count];
        FMResultSet *result = [db executeQuery:sql];
        while ([result next]) {
            [messages addObject:[self messageWith:result]];
        }
        [messages reverse];
    }];
    return messages;
}


// 根据uid和聊天内容模糊搜索
- (NSArray<BTMessageModel *> *)queryMessagesWithUid:(NSInteger)uid byContent:(NSString *)content {
//    long long fromTime = [ChatTool shareChatTool].currentTimestamp - 3 * 60 * 60 * 1000;
//    [self deleteMessageBeforeTimestamp:fromTime];
    NSMutableArray *messages = [NSMutableArray new];
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        // 发送给uid的消息  接收从uid发来的消息
        NSString *sql = [NSString stringWithFormat:@"select * from %@ where (messageDirection = 0 and rfuuid = %ld and content like '%%%@%%') or (messageDirection = 1 and receiveUid = %ld and content like '%%%@%%')", self.tableName, uid, content, uid, content];
        FMResultSet *result = [db executeQuery:sql];
        while ([result next]) {
            [messages addObject:[self messageWith:result]];
        }
    }];
    return messages;
}

- (BTMessageModel *)messageWith:(FMResultSet *)result {
    BTMessageModel *msg = [BTMessageModel new];
    msg.messageType = [result intForColumn:@"messageType"];
    msg.messageDirection = [result intForColumn:@"messageDirection"];
    msg.uid = [result intForColumn:@"uid"];
    msg.username = [result stringForColumn:@"username"];
    msg.avatar = [result stringForColumn:@"avatar"];
    msg.type = [result stringForColumn:@"type"];
    msg.src = [result stringForColumn:@"src"];
    msg.content = [result stringForColumn:@"content"];
    msg.time = [result stringForColumn:@"time"];
    msg.specialType = [result intForColumn:@"specialType"];
    msg.groupId = [result intForColumn:@"groupId"];
    msg.authority = [result intForColumn:@"authority"];
    msg.mine = [result intForColumn:@"mine"];
    msg.timestamp = [result longLongIntForColumn:@"timestamp"];
    msg.cid = [result longLongIntForColumn:@"cid"];
    msg.receiveUid = [result intForColumn:@"receiveUid"];
    msg.unreadCount = [result intForColumn:@"unreadCount"];
    msg.messageStatus =  [result intForColumn:@"messageStatus"];
    msg.messageId = [result longLongIntForColumn:@"messageId"];
    
    msg.msgtype=[result intForColumn:@"msgtype"];
    msg.msg_id=[result stringForColumn:@"msg_id"];
    msg.clientuuid= [result stringForColumn:@"clientuuid"];
    msg.msg = [result stringForColumn:@"msg"];
    msg.gId = [result stringForColumn:@"gId"];
    msg.head=[result stringForColumn:@"head"];
    msg.f_uuid=[result stringForColumn:@"f_uuid"];
    msg.nickname=[result stringForColumn:@"nickname"];
    msg.token=[result stringForColumn:@"token"];
    msg.udid=[result stringForColumn:@"udid"];
    msg.createtime=[result stringForColumn:@"createtime"];
    msg.chatType = [result intForColumn:@"chatType"];
    msg.rfuuid=[result stringForColumn:@"rfuuid"];
    
    if (msg.msgtype == MessageTypeText || msg.msgtype == MessageTypeRecall || msg.msgtype == MessageTypeTime || msg.msgtype == MessageTypeInviteAddGroup ||msg.msgtype == MessageTypeMangerDeleteMember ||msg.msgtype == MessageTypeGroupDissolution ||msg.msgtype == MessageTypeStartGroupChatting ||msg.msgtype == MessageTypeAddedBlacklist ||msg.msgtype == MessageTypeNotInGroup ||msg.msgtype == MessageTypeNotFriend ||msg.msgtype == MessageTypeSendFailure  ||msg.msgtype == MessageTypeSendBanned ) {
        return msg;
    } else if (msg.msgtype == MessageTypeImage) {
        ImageMessageModel *imageMsg = [ImageMessageModel mj_objectWithKeyValues:msg.mj_keyValues];
        imageMsg.image = [UIImage imageWithData:[result dataForColumn:@"image"]];
        imageMsg.path = [result stringForColumn:@"path"];
        return imageMsg;
    } else if (msg.msgtype == MessageTypeVoice) {
        VoiceMessageModel *voiceMsg = [VoiceMessageModel mj_objectWithKeyValues:msg.mj_keyValues];
        voiceMsg.path = [result stringForColumn:@"path"];
        voiceMsg.duration = [result intForColumn:@"duration"];
        return voiceMsg;
    }
    return nil;
}

#pragma mark - getter

- (NSString *)tableName {
    UserModel * model_user= [[LoginManager shareLoginManager] getLoginCustomer];
    return  [NSString stringWithFormat:@"t_chatMessageList_%@", model_user.fuuid];
}
@end
